import os
import ast
import json
import warnings
import shutil
from addict import Dict
from typing import Any
from wwengine.utils import check_file_exist

class ConfigDict(Dict):
    def __init__(self, *args, **kwargs):
        for arg in args:
            if not arg:
                continue
            if isinstance(arg, ConfigDict):
                pass
            elif isinstance(arg, dict):
                for key, val in arg.items():
                    self[key] = self._hook(val)

    @classmethod
    def _hook(cls, item):
        if isinstance(item, dict):
            # 如果val是dict则进行递归
            return cls(item)
        elif isinstance(item, (list, tuple)):
            return type(item)(cls._hook(elem) for elem in item)
        return item

    def try_get(self, key):
        if key in self:
            return self[key]
        else:
            warnings.warn("key访问失败")
            return None

    def exist(self, key:str) -> bool:
        return key in self

    def __iter__(self):
        # Implement `__iter__` to overwrite the unpacking operator `**cfg_dict`
        # to get the built lazy object
        return iter(self.keys())

    def items(self):
        """Yield the keys and values of the dictionary.

        If class attribute ``lazy`` is False, the value of ``LazyObject`` or
        ``LazyAttr`` will be built and returned.
        """
        items = []
        for key, value in super().items():
            items.append((key, value))
        return items

class Config:
    def __init__(self,
                 cfg_dict:dict=None,
                 filename: str = None):
        cfg_dict = ConfigDict(cfg_dict)
        super().__setattr__('_cfg_dict',cfg_dict)
        super().__setattr__('_filename',filename)

    @staticmethod
    def fromfile(filename: str):
        check_file_exist(filename)
        fileExtname = os.path.splitext(filename)[1]
        if fileExtname not in ['.json']:
            raise OSError('Only py/yml/yaml/json type are supported now!')
        try:
            with open(filename) as f:
                data = json.load(f)
            print(data)

        except Exception as e:
            raise e
        return Config(data,filename)

    # def get(self, key:str):
    #     if key in self.cfg_dict.key():
    #         pass

    def __len__(self):
        return len(self._cfg_dict)

    def __getattr__(self, name: str) -> Any:
        return getattr(self._cfg_dict, name)

    def __getitem__(self, name):
        return self._cfg_dict.__getitem__(name)

    def __setattr__(self, name, value):
        if isinstance(value, dict):
            value = ConfigDict(value)
        self._cfg_dict.__setattr__(name, value)

    def __setitem__(self, name, value):
        if isinstance(value, dict):
            value = ConfigDict(value)
        self._cfg_dict.__setitem__(name, value)

    def __iter__(self):
        return iter(self._cfg_dict)

    def backup(self, path_dst):
        assert self._filename.endswith('.json') and os.path.exists(path_dst), "cfg_file format <{}> error or path_dst " \
                                                                             "<{}> not exist".format(self._filename,
                                                                                                     path_dst)
        shutil.copy(self._filename, path_dst)
